﻿using System;
using System.Threading;
using NLog;
using Quartz;
using Quartz.Impl;

namespace ICommonLibrary.Cocurrent {
    
    public class QuartzUtil {

        private const string CommandKey = "__Command__";
        private const string StateKey = "__State__";
        private static int _jobCount;

        public static IJobDetail CreateJob(Action<object> command, object state) {
            string name = "QuartzUtil.CommandJob#" + Interlocked.Increment(ref _jobCount);
            var job = new JobDetailImpl(name, null, typeof(CommandJob));
            job.JobDataMap[CommandKey] = command;
            job.JobDataMap[StateKey] = state;
            return job;
        }

        public static IJobDetail CreateJob(Action command) {
            string name = "QuartzUtil.SimpleJob#" + Interlocked.Increment(ref _jobCount);
            var job = new JobDetailImpl(name, null, typeof(StatefulCommandJob));
            job.JobDataMap[CommandKey] = command;
            return job;
        }

        private class CommandJob : IJob {

            public void Execute(IJobExecutionContext context) {
                try {
                    JobDataMap data = context.JobDetail.JobDataMap;
                    ((Action<object>)data.Get(CommandKey))(data.Get(StateKey));
                } 
                catch(Exception e) {
                    LogManager.GetCurrentClassLogger().ErrorException("Executing Quartz.Util command job failed:" + e.Message, e);
                }
            }
        }

        private class StatefulCommandJob : IJob {

            public void Execute(IJobExecutionContext context) {
                try {
                    JobDataMap data = context.JobDetail.JobDataMap;
                    ((Action)data.Get(CommandKey))();
                }
                catch (Exception e) {
                    LogManager.GetCurrentClassLogger().ErrorException("Executing Quartz.Util stateful command job failed:" + e.Message, e);
                }
            }
        }
        
    }
}
